using Microsoft.AspNetCore.Http;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;

namespace CKY.AgentPlatform.Performance
{
    /// <summary>
    /// 响应压缩中间件
    /// 用于压缩响应内容，减少网络传输时间
    /// </summary>
    public class CompressionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly CompressionOptions _options;

        public CompressionMiddleware(RequestDelegate next, CompressionOptions options)
        {
            _next = next;
            _options = options;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var request = context.Request;
            var response = context.Response;

            // 检查是否应该压缩响应
            if (!ShouldCompressResponse(request, response))
            {
                await _next(context);
                return;
            }

            // 检查客户端支持的压缩算法
            var acceptEncoding = request.Headers["Accept-Encoding"].ToString();
            if (string.IsNullOrEmpty(acceptEncoding))
            {
                await _next(context);
                return;
            }

            // 根据客户端支持选择压缩算法
            var compressionProvider = SelectCompressionProvider(acceptEncoding);
            if (compressionProvider == null)
            {
                await _next(context);
                return;
            }

            // 设置压缩头信息
            response.Headers["Content-Encoding"] = compressionProvider.EncodingName;
            response.Headers["Vary"] = "Accept-Encoding";

            // 使用压缩流包装原始响应流
            var originalBody = response.Body;
            using var compressedStream = compressionProvider.CreateStream(originalBody);
            response.Body = compressedStream;

            try
            {
                await _next(context);
            }
            finally
            {
                // 确保压缩流被刷新
                await compressedStream.FlushAsync();
                response.Body = originalBody;
            }
        }

        private bool ShouldCompressResponse(HttpRequest request, HttpResponse response)
        {
            // 不压缩已经压缩的内容类型
            var contentType = response.ContentType;
            if (string.IsNullOrEmpty(contentType))
                return true;

            // 不应该压缩的内容类型
            var nonCompressibleTypes = new[]
            {
                "image/",
                "video/",
                "audio/",
                "application/zip",
                "application/x-gzip",
                "application/x-rar-compressed",
                "application/x-tar",
                "application/x-7z-compressed"
            };

            foreach (var type in nonCompressibleTypes)
            {
                if (contentType.StartsWith(type, System.StringComparison.OrdinalIgnoreCase))
                    return false;
            }

            // 检查响应大小阈值
            if (response.ContentLength.HasValue && response.ContentLength.Value < _options.MinimumSizeToCompress)
                return false;

            return true;
        }

        private ICompressionProvider SelectCompressionProvider(string acceptEncoding)
        {
            // 按优先级检查支持的压缩算法
            if (acceptEncoding.Contains("br", System.StringComparison.OrdinalIgnoreCase))
                return new BrotliCompressionProvider();

            if (acceptEncoding.Contains("gzip", System.StringComparison.OrdinalIgnoreCase))
                return new GzipCompressionProvider();

            if (acceptEncoding.Contains("deflate", System.StringComparison.OrdinalIgnoreCase))
                return new DeflateCompressionProvider();

            return null;
        }
    }

    /// <summary>
    /// 压缩配置选项
    /// </summary>
    public class CompressionOptions
    {
        /// <summary>
        /// 启用压缩的最小响应大小（字节）
        /// </summary>
        public int MinimumSizeToCompress { get; set; } = 1024;

        /// <summary>
        /// 启用压缩的MIME类型
        /// </summary>
        public string[] MimeTypes { get; set; } = new[]
        {
            "text/plain",
            "text/html",
            "text/css",
            "text/javascript",
            "application/javascript",
            "application/json",
            "application/xml",
            "text/xml",
            "application/xhtml+xml",
            "application/rss+xml"
        };
    }

    /// <summary>
    /// 压缩提供者接口
    /// </summary>
    public interface ICompressionProvider
    {
        string EncodingName { get; }
        Stream CreateStream(Stream outputStream);
    }

    /// <summary>
    /// Gzip压缩提供者
    /// </summary>
    public class GzipCompressionProvider : ICompressionProvider
    {
        public string EncodingName => "gzip";

        public Stream CreateStream(Stream outputStream)
        {
            // 暂时禁用压缩功能，等待后续实现
            return outputStream;
        }
    }

    /// <summary>
    /// Brotli压缩提供者
    /// </summary>
    public class BrotliCompressionProvider : ICompressionProvider
    {
        public string EncodingName => "br";

        public Stream CreateStream(Stream outputStream)
        {
            // 暂时禁用压缩功能，等待后续实现
            return outputStream;
        }
    }

    /// <summary>
    /// Deflate压缩提供者
    /// </summary>
    public class DeflateCompressionProvider : ICompressionProvider
    {
        public string EncodingName => "deflate";

        public Stream CreateStream(Stream outputStream)
        {
            return new DeflateStream(outputStream, CompressionMode.Compress, true);
        }
    }
}